1. 컨테이너 런타임 개요
4.1. 컨테이너 런타임 개요
도커나 쿠버네티스에서 컨테이너를 실행할 때 컨테이너는 컨테이너 런타임으로 만들어짐. 컨테이너 런타임은 쿠버네티스와 같은 상위 오케스트레이터의 지시를 받아서 머신에 파드와 컨테이너를 작성하고 관리함
4.1.1 도커, 쿠버네티스, 컨테이너 런타임의 관계
도커와 컨테이너 런타임:
도커 데몬은 사용자로부터 도커 CLI 등에서 컨테이너 작성 지시를 받거나, 레지스트리와 통신, 이미지, 컨테이너, 네트워크 등을 관리함
도커의 컨테이너 실행 흐름:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
[사용자]
│
│ docker run nginx
↓
[Docker CLI]
│
│ REST API 요청
↓
[Docker Daemon (dockerd)]
│
├─ 레지스트리에서 이미지 풀
├─ 컨테이너 실행 설정 준비
│ └─ 실행 명령어, 환경 변수 등
├─ 루트 파일시스템 준비
│ └─ 이미지 레이어에서 생성
↓
[OCI 런타임 (runc)]
│
│ 설정 + 루트 파일시스템을 받음
↓
[컨테이너 생성]
│
└─ 호스트와 격리된 실행 환경 작성
도커 데몬은 컨테이너로 실행하는 애플리케이션을 위한 호스트와 격리된 실행 환경을 만드는 작업에 저수준 계층의 런타임 OCI 런타임을 사용함. OCI 런타임 규격은 OCI Runtime Specification으로 업계 표준 규격이 정해져 있음
쿠버네티스와 컨테이너 런타임:
각 노드의 kubelet은 자신의 노드에 파드가 스케줄링되면 CRI 런타임에 파드 작성을 지시함
쿠버네티스의 컨테이너 실행 흐름:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
[API 서버]
│
│ 파드 스케줄링 지시
↓
[kubelet]
│
│ CRI (Container Runtime Interface) API 호출
↓
[CRI 런타임 (containerd, CRI-O)]
│
├─ 레지스트리에서 이미지 풀
├─ 파드/컨테이너 상태 관리
├─ 네트워크 관리 (CNI 플러그인 사용)
├─ 컨테이너 실행 설정 준비
├─ 루트 파일시스템 준비
↓
[OCI 런타임 (runc)]
│
│ 설정 + 루트 파일시스템을 받음
↓
[컨테이너 생성]
│
└─ 호스트와 격리된 실행 환경 작성
kubelet은 **CRI (Container Runtime Interface)**로 정해진 표준 API를 통해 CRI 런타임을 조작함. CRI 런타임은 파드 작성과 관리를 위해 레지스트리와의 통신과 이미지, 파드, 컨테이너 상태 관리, 네트워크 관리를 수행함
도커와 쿠버네티스 상호 운용성:
표준 규격 기반 상호 운용:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
[docker build]
│
│ OCI Image Specification 준수
↓
[이미지 생성]
│
│ OCI Distribution Specification 준수
↓
[레지스트리 푸시]
│
│ Docker Hub, ECR, GCR 등
↓
[공유 가능]
│
├─ 도커에서 실행 가능
│ └─ docker run <image>
│
└─ 쿠버네티스에서 실행 가능
└─ kubectl run --image=<image>
도커와 쿠버네티스는 똑같은 방식으로 레지스트리를 조작해 이미지를 가져오고 OCI 런타임을 사용해 컨테이너 실행 환경을 작성함. 따라서 사용자는 환경에 따라 도커와 쿠버네티스를 조합해서 서비스를 개발하고 운영할 수 있음
OCI 표준 규격:
| 규격 | 설명 | 역할 |
|---|---|---|
| OCI Runtime Specification | 컨테이너 실행 환경 규격 | 컨테이너 생성/실행 방법 정의 |
| OCI Image Specification | 컨테이너 이미지 규격 | 이미지 포맷 정의 |
| OCI Distribution Specification | 레지스트리 통신 규격 | 이미지 배포 방법 정의 |
도커와 쿠버네티스의 높은 상호 운용성이 가능한 요인은 업계에서 정한 컨테이너 관련 표준 규격 덕분임. Open Container Initiative (OCI) 단체가 OCI 런타임, 이미지, 레지스트리에 각각 표준 규격을 정함
- 컨테이너 런타임: 컨테이너를 생성하고 실행하는 소프트웨어. 고수준 런타임과 저수준 런타임으로 구분됨
- OCI (Open Container Initiative): 컨테이너 표준을 제정하는 단체. Docker, Google, CoreOS 등이 설립하여 Linux Foundation 산하에서 운영
- OCI Runtime Specification: 컨테이너 실행 환경 표준 규격. runc 등 저수준 런타임이 따르는 규격
- OCI Image Specification: 컨테이너 이미지 포맷 표준 규격. 이미지의 레이어 구조와 메타데이터 형식 정의
- OCI Distribution Specification: 레지스트리 통신 표준 규격. 이미지 push/pull API 정의
- CRI (Container Runtime Interface): kubelet과 CRI 런타임 간 통신을 위한 쿠버네티스 표준 API
4.1.2 두 종류의 런타임 레이어
컨테이너 런타임 소프트웨어는 역할에 따라 두 단계의 계층으로 나뉨
런타임 계층 구조:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
[사용자/kubelet]
│
│ 컨테이너 생성 요청
↓
[고수준 런타임 (High-Level Runtime)]
│
├─ 역할:
│ ├─ 레지스트리와 통신
│ ├─ 이미지 관리
│ ├─ 컨테이너/파드 상태 관리
│ └─ 네트워크 관리
│
├─ 예시:
│ ├─ Docker (Docker Engine)
│ ├─ containerd (CRI 런타임)
│ └─ CRI-O (CRI 런타임)
│
│ 실행 설정 + 루트 파일시스템 전달
↓
[저수준 런타임 (Low-Level/OCI Runtime)]
│
├─ 역할:
│ ├─ 호스트와 격리된 실행 환경 생성
│ ├─ 네임스페이스, cgroups 설정
│ └─ 컨테이너 직접 조작
│
├─ 예시:
│ ├─ runc (기본)
│ ├─ crun (경량)
│ └─ gVisor, Kata Containers (보안 강화)
│
↓
[컨테이너]
│
└─ 격리된 실행 환경에서 애플리케이션 실행
런타임 분류:
| 구분 | 고수준 런타임 | 저수준(OCI) 런타임 |
|---|---|---|
| 역할 | 이미지/컨테이너/네트워크 관리 | 격리된 실행 환경 생성 |
| 규격 | CRI (Container Runtime Interface) | OCI Runtime Specification |
| 예시 | Docker, containerd, CRI-O | runc, crun, gVisor |
| 호출자 | 사용자, kubelet | 고수준 런타임 |
- 고수준 런타임(High-Level Runtime): 이미지, 컨테이너, 네트워크를 관리하는 상위 계층 런타임. Docker, containerd, CRI-O 등
- 저수준 런타임(Low-Level/OCI Runtime): 호스트와 격리된 실행 환경을 생성하는 하위 계층 런타임. runc, crun, gVisor 등
- containerd: CNCF 프로젝트로, Docker에서 분리된 CRI 런타임. EKS, GKE, AKS의 기본 런타임
- CRI-O: Red Hat 주도로 개발된 쿠버네티스 전용 CRI 런타임. OpenShift의 기본 런타임
- runc: OCI Runtime Specification의 참조 구현체. Docker와 쿠버네티스에서 기본 저수준 런타임으로 사용
4.1.3 CRI 런타임, OCI 런타임 연동과 파드 작성 흐름
kubelet의 파드 감시:
쿠버네티스의 노드에서 실행되는 kubelet은 API 서버 등에서 발생한 파드 관련 변경 내용을 감시함. 파드가 자신의 노드에 스케줄링되거나 파드에 관련된 어떤 변경이 있으면 해당 노드에서 CRI 런타임을 호출함
파드 작성 전체 흐름:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
[1단계: kubelet 감시]
│
kubelet이 API 서버 변경 감시
├─ 새 파드 스케줄링 감지
└─ 파드 관련 변경 감지
↓
[2단계: CRI 런타임 호출]
│
kubelet → CRI 런타임 (gRPC API)
├─ 이미지 풀 요청
├─ 파드 생성 요청
└─ 컨테이너 생성 요청
↓
[3단계: CRI 런타임 작업]
│
CRI 런타임 수행 작업:
├─ 레지스트리에서 이미지 풀
├─ 이미지 압축 해제
│ └─ 컨테이너 루트 파일시스템 생성
├─ 컨테이너 실행 환경 설정 파일 준비
├─ CNI 플러그인 사용
│ └─ 파드용 네트워크 인터페이스 생성
└─ 네트워크 설정을 실행 환경 설정 파일에 반영
↓
[4단계: OCI 런타임 호출]
│
CRI 런타임 → OCI 런타임
├─ 컨테이너 실행 환경 설정 파일 전달
└─ 루트 파일시스템 전달
↓
[5단계: 컨테이너 생성]
│
OCI 런타임 수행 작업:
├─ 호스트와 격리된 실행 환경 작성
│ ├─ 네임스페이스 설정
│ ├─ cgroups 설정
│ └─ 보안 설정
└─ 컨테이너 내 애플리케이션 실행
↓
[6단계: 파드 완성]
│
kubelet이 추가 컨테이너 생성 지시
└─ 네트워크 인터페이스 공유하는 컨테이너 그룹 완성
CRI API 통신:
kubelet은 CRI 런타임에 gRPC API를 사용해서 지시하는데, 이 API가 **Container Runtime Interface (CRI)**로 쿠버네티스에 정의되어 있음
CRI API 주요 서비스:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
[RuntimeService]
│
├─ RunPodSandbox() # 파드 샌드박스 생성
├─ StopPodSandbox() # 파드 샌드박스 중지
├─ RemovePodSandbox() # 파드 샌드박스 삭제
├─ CreateContainer() # 컨테이너 생성
├─ StartContainer() # 컨테이너 시작
├─ StopContainer() # 컨테이너 중지
└─ RemoveContainer() # 컨테이너 삭제
[ImageService]
│
├─ PullImage() # 이미지 풀
├─ ListImages() # 이미지 목록
└─ RemoveImage() # 이미지 삭제
OCI Runtime Specification:
OCI 런타임 규격은 **Open Container Initiative (OCI)**에서 OCI Runtime Specification으로 정함. CRI 런타임은 이 규격에 따라 OCI 런타임을 실행해서 애플리케이션 실행 환경, 즉 컨테이너를 작성함
OCI Runtime Specification 주요 구성:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
[config.json]
│
컨테이너 실행 환경 설정 파일
│
├─ ociVersion: "1.0.0"
│
├─ process:
│ ├─ args: ["/bin/sh", "-c", "nginx"]
│ ├─ env: ["PATH=/usr/bin"]
│ ├─ cwd: "/"
│ └─ user: {uid: 0, gid: 0}
│
├─ root:
│ └─ path: "rootfs/"
│
├─ mounts:
│ └─ 파일시스템 마운트 정보
│
├─ linux:
│ ├─ namespaces: [pid, network, mount, ...]
│ ├─ cgroups: {cpu, memory, ...}
│ └─ seccomp: 시스템 콜 제한
│
└─ hooks:
└─ 컨테이너 생명주기 훅
[rootfs/]
│
컨테이너 루트 파일시스템
│
├─ bin/
├─ etc/
├─ usr/
└─ ...
- gRPC API: Google이 개발한 고성능 원격 프로시저 호출 프레임워크. CRI 통신에 사용
- RuntimeService: CRI의 파드/컨테이너 라이프사이클 관리 서비스. RunPodSandbox, CreateContainer 등의 메서드 제공
- ImageService: CRI의 이미지 관리 서비스. PullImage, ListImages 등의 메서드 제공
- 파드 샌드박스(Pod Sandbox): 파드의 네트워크 네임스페이스를 유지하는 특수 컨테이너. pause 컨테이너라고도 함
- CNI 플러그인: 컨테이너 네트워크 인터페이스를 설정하는 플러그인. CRI 런타임이 호출하여 파드에 IP 주소 할당
- config.json: OCI Runtime Specification에 정의된 컨테이너 설정 파일. 실행 명령, 환경 변수, 네임스페이스 등 포함
- rootfs: 컨테이너의 루트 파일시스템. 이미지 레이어를 병합하여 생성
런타임 구성 비교
도커 vs 쿠버네티스 런타임 스택:
런타임 스택 비교:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
[Docker]
사용자
↓
Docker CLI
↓
Docker Daemon (dockerd)
↓
containerd
↓
runc (OCI Runtime)
↓
컨테이너
vs
[Kubernetes]
API 서버
↓
kubelet
↓
CRI 런타임 (containerd 또는 CRI-O)
↓
OCI 런타임 (runc 등)
↓
컨테이너
핵심 정리:
| 항목 | 설명 |
|---|---|
| 고수준 런타임 | 이미지/컨테이너/네트워크 관리 (Docker, containerd, CRI-O) |
| 저수준 런타임 | 격리된 실행 환경 생성 (runc, crun, gVisor) |
| CRI | kubelet과 고수준 런타임 간 표준 인터페이스 |
| OCI Runtime Spec | 고수준 런타임과 저수준 런타임 간 표준 규격 |
| 상호 운용성 | OCI 표준 덕분에 도커 이미지를 쿠버네티스에서 실행 가능 |
참고 자료
공식 문서:
- OCI Runtime Specification: https://github.com/opencontainers/runtime-spec
- OCI Image Specification: https://github.com/opencontainers/image-spec
- Kubernetes CRI: https://kubernetes.io/docs/concepts/architecture/cri/
- containerd: https://containerd.io/
- CRI-O: https://cri-o.io/